import { Platform } from 'react-native';
import * as FileSystem from 'expo-file-system';
import { v4 as uuidv4 } from 'uuid';
import { MultimodalInput, ProcessingOptions } from '../../shared/types/app';
import { ImageOptimizer } from '../../utils/imageOptimization';
import { VideoCompressor } from '../../utils/videoCompression';

/**
 * Manages multimodal inputs for AI interactions
 */
export class MultimodalInputManager {
    private sessionId: string;
    private processingOptions: ProcessingOptions;

    constructor(options: ProcessingOptions = {}) {
        this.sessionId = uuidv4();
        this.processingOptions = options;
    }

    /**
     * Creates a multimodal input from various sources
     */
    async createMultimodalInput(params: {
        text?: string;
        imageUris?: string[];
        audioUri?: string;
        videoUri?: string;
        contextId?: string;
    }): Promise<MultimodalInput> {
        const { text, imageUris, audioUri, videoUri, contextId } = params;

        // Create base input structure
        const input: MultimodalInput = {
            id: uuidv4(),
            timestamp: Date.now(),
            contextId: contextId || this.sessionId
        };

        // Add text if provided
        if (text) {
            input.text = text;
        }

        // Process images if provided
        if (imageUris && imageUris.length > 0) {
            input.images = await this.processImages(imageUris);
        }

        // Process audio if provided
        if (audioUri) {
            input.audio = await this.processAudio(audioUri);
        }

        // Process video if provided
        if (videoUri) {
            input.video = await this.processVideo(videoUri);
        }

        return input;
    }

    /**
     * Process images for optimal API submission
     */
    private async processImages(imageUris: string[]): Promise<string[]> {
        const processedImages: string[] = [];

        for (const uri of imageUris) {
            try {
                // Optimize image
                const optimizedUri = await ImageOptimizer.optimize(uri, this.processingOptions.image);

                // Convert to base64 for API
                const base64Data = await ImageOptimizer.uriToBase64(optimizedUri);

                // Add appropriate data URI prefix
                const imageType = optimizedUri.toLowerCase().endsWith('png') ? 'png' : 'jpeg';
                const dataUri = `data:image/${imageType};base64,${base64Data}`;

                processedImages.push(dataUri);
            } catch (error) {
                console.error('Error processing image:', error);
            }
        }

        return processedImages;
    }

    /**
     * Process audio for optimal API submission
     */
    private async processAudio(audioUri: string): Promise<string> {
        try {
            // In a real implementation, we would process the audio here
            // (Convert format, optimize bitrate, etc.)

            // Convert to base64 for API
            const base64Data = await FileSystem.readAsStringAsync(audioUri, {
                encoding: FileSystem.EncodingType.Base64
            });

            // Determine audio type from file extension
            const extension = audioUri.split('.').pop()?.toLowerCase() || 'mp3';
            const mimeType = extension === 'wav' ? 'audio/wav' :
                extension === 'aac' ? 'audio/aac' : 'audio/mpeg';

            // Add appropriate data URI prefix
            return `data:${mimeType};base64,${base64Data}`;
        } catch (error) {
            console.error('Error processing audio:', error);
            return audioUri; // Return original on error
        }
    }

    /**
     * Process video for optimal API submission
     */
    private async processVideo(videoUri: string): Promise<string> {
        try {
            // Compress video if needed
            const compressedUri = await VideoCompressor.compress(
                videoUri,
                this.processingOptions.video
            );

            // Convert to base64 for API
            const base64Data = await FileSystem.readAsStringAsync(compressedUri, {
                encoding: FileSystem.EncodingType.Base64
            });

            // Determine video type from file extension
            const extension = compressedUri.split('.').pop()?.toLowerCase() || 'mp4';
            const mimeType = extension === 'mov' ? 'video/quicktime' :
                extension === 'webm' ? 'video/webm' : 'video/mp4';

            // Add appropriate data URI prefix
            return `data:${mimeType};base64,${base64Data}`;
        } catch (error) {
            console.error('Error processing video:', error);
            return videoUri; // Return original on error
        }
    }

    /**
     * Formats multimodal input for API request
     */
    formatForAPI(input: MultimodalInput): any[] {
        const content: any[] = [];

        // Add text content
        if (input.text) {
            content.push({
                type: 'text',
                text: input.text
            });
        }

        // Add image content
        if (input.images && input.images.length > 0) {
            for (const image of input.images) {
                content.push({
                    type: 'image',
                    image: image
                });
            }
        }

        // Add audio content
        if (input.audio) {
            content.push({
                type: 'audio',
                audio: input.audio
            });
        }

        // Add video content
        if (input.video) {
            content.push({
                type: 'video',
                video: input.video
            });
        }

        return content;
    }

    /**
     * Creates a message object for the API request
     */
    createAPIMessage(input: MultimodalInput, role: 'user' | 'assistant' | 'system' = 'user'): any {
        return {
            role,
            content: this.formatForAPI(input)
        };
    }

    /**
     * Sets global processing options for all inputs
     */
    setProcessingOptions(options: ProcessingOptions): void {
        this.processingOptions = {
            ...this.processingOptions,
            ...options
        };
    }

    /**
     * Cleans up temporary files created during processing
     */
    async cleanupTempFiles(): Promise<void> {
        try {
            // Implementation would depend on how we track temp files
            // For a simple implementation, we could delete all temp files in the cache directory
            // that match our naming pattern and are older than a certain threshold

            console.log('Cleanup of temporary files would happen here');
        } catch (error) {
            console.error('Error cleaning up temp files:', error);
        }
    }
} 